package cn.superfw.filedownload;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * 通用URL资源下载器
 */
public class URLFileDownloader {
	/**
	 * 通过资源的URL下载文件到指定目录
	 * @param url 资源URL
	 * @param dest 资源本地存储目的地
	 * @return 下载结果 true 成功 / false 失败
	 */
	public boolean download(String resURL, OutputStream dest) {

		URL url = null;
		HttpURLConnection conn=null;

		if (dest == null) {
			System.err.println("资源本地存储目的地不存在！");
			return false;
		}

		try {
			url = new URL(resURL);
			conn = (HttpURLConnection)url.openConnection();
			conn.setReadTimeout(3000);
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				InputStream is = conn.getInputStream();
				copy(is, dest);
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
			if (dest != null) {
				try {
					dest.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return true;
	}

	/**
	 * 通过资源的URL下载文件到指定目录
	 * @param url 资源URL
	 * @param localPath 资源本地存储目录
	 * @param fileName 文件名
	 * @return 下载结果 true 成功 / false 失败
	 */
	public boolean download(String resURL, String localPath, String fileName) {

		try {
			return download(resURL, new FileOutputStream(new File(localPath, fileName)));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}


	/**
	 * 通过资源的URL下载文件到指定目录
	 * @param url 资源URL
	 * @param dest 资源本地存储目的地
	 * @return 下载结果 true 成功 / false 失败
	 */
	public boolean httpsDownload(String resURL, OutputStream dest) {

		URL url = null;
		HttpsURLConnection conn=null;

		if (dest == null) {
			System.err.println("资源本地存储目的地不存在！");
			return false;
		}

		try {
			url = new URL(resURL);
			conn = (HttpsURLConnection)url.openConnection();
			conn.setReadTimeout(3000);

            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            conn.setSSLSocketFactory(ssf);

			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				InputStream is = conn.getInputStream();
				copy(is, dest);
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
			if (dest != null) {
				try {
					dest.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return true;
	}

	/**
	 * 通过资源的URL下载文件到指定目录
	 * @param url 资源URL
	 * @param localPath 资源本地存储目录
	 * @param fileName 文件名
	 * @return 下载结果 true 成功 / false 失败
	 */
	public boolean httpsDownload(String resURL, String localPath, String fileName) {

		try {
			return httpsDownload(resURL, new FileOutputStream(new File(localPath, fileName)));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 流拷贝
	 * @param is 输入流
	 * @param os 输出流
	 * @throws IOException 异常
	 */
	private void copy(InputStream is, OutputStream os) throws IOException {
		byte[] buffer = new byte[4096];
		int n = 0;
		while (-1 != (n = is.read(buffer))) {
			os.write(buffer, 0, n);
		}
	}

	private class MyX509TrustManager implements X509TrustManager {

		// 检查客户端证书
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		// 检查服务器端证书
	    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		// 返回受信任的X509证书数组
	    public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}

}
